﻿//TradeGenerator.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.Testing
{
	using System;

	using Ecng.Common;

	using StockSharp.BusinessEntities;

	/// <summary>
	/// Генератор тиковых сделок случайным методом.
	/// </summary>
	public abstract class TradeGenerator : MarketDataGenerator<Trade>
	{
		/// <summary>
		/// Инициализировать <see cref="TradeGenerator"/>.
		/// </summary>
		/// <param name="security">Инструмент, для которого необходимо генерировать данные.</param>
		protected TradeGenerator(Security security)
			: base(security)
		{
			IdGenerator = new IdGenerator();
		}

		/// <summary>
		/// Генерировать значение для <see cref="Trade.OrderDirection"/>. По-умолчанию отключено.
		/// </summary>
		public bool GenerateDirection { get; set; }

		private IdGenerator _idGenerator;

		/// <summary>
		/// Генератор номера сделки <see cref="Trade.Id"/>.
		/// </summary>
		public IdGenerator IdGenerator
		{
			get { return _idGenerator; }
			set
			{
				if (value == null)
					throw new ArgumentNullException("value");

				_idGenerator = value;
			}
		}

		/// <summary>
		/// Сгенерировать случайную сделку.
		/// </summary>
		/// <param name="time">Время сделки.</param>
		/// <returns>Случайная сделка.</returns>
		public virtual Trade Generate(DateTime time)
		{
			var trade = new Trade
			{
				Security = Security,
				Id = IdGenerator.Next,
				//Time = time,
				OrderDirection = (GenerateDirection ? RandomGen.GetEnum<OrderDirections>() : (OrderDirections?)null),
				Volume = Volumes.Next()
			};

			Generate(trade, time);

			return trade;
		}
	}

	/// <summary>
	/// Генератор сделок на основе нормального распределения.
	/// </summary>
	public class RandomWalkTradeGenerator : TradeGenerator
	{
		/// <summary>
		/// Создать <see cref="RandomWalkTradeGenerator"/>.
		/// </summary>
		/// <param name="security">Инструмент, для которого необходимо генерировать данные.</param>
		/// <param name="startPrice">Цена, от которой начинается расчёт нормального распределения.</param>
		public RandomWalkTradeGenerator(Security security, decimal startPrice)
			: base(security)
		{
			_lastTradePrice = startPrice;
		}

		private decimal _lastTradePrice;

		/// <summary>
		/// Сгенерировать маркет-данные.
		/// </summary>
		/// <param name="data">Маркет-данные.</param>
		/// <param name="time">Текущее время.</param>
		public override void Generate(Trade data, DateTime time)
		{
			if (data == null)
				throw new ArgumentNullException("data");

			_lastTradePrice += RandomGen.GetInt(-MaxPriceStepCount, MaxPriceStepCount) * Security.MinStepSize;

			if (_lastTradePrice <= 0)
				_lastTradePrice = Security.MinStepSize;

			data.Price = _lastTradePrice;
			data.Time = time;

			base.Generate(data, time);
		}

		/// <summary>
		/// Создать копию генератора.
		/// </summary>
		/// <returns>Копия.</returns>
		public override MarketDataGenerator<Trade> Clone()
		{
			return new RandomWalkTradeGenerator(Security, _lastTradePrice)
			{
				MaxVolume = MaxVolume,
				MinVolume = MinVolume,
				MaxPriceStepCount = MaxPriceStepCount,
				Interval = Interval,
				Volumes = Volumes,
				Steps = Steps,

				GenerateDirection = GenerateDirection,
				IdGenerator = IdGenerator
			};
		}
	}
}